package com.sunway.resource2es.util;

import co.elastic.clients.elasticsearch._types.analysis.TokenChar;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.IndexSettings;

import java.util.List;

/**
 * es mapping操作工具类
 *
 * @author lxw
 * @date 2024/7/29 16:58
 **/
public class EsMappingUtil {


    /**
     * 初始化映射setting,默认分片书1，副本0
     * <p>
     * 默认ngram分词器，单个字符分词 <br/>
     * tokenizer ==>ngram_tokenizer<br/>
     * analyzer ==>ngram_analyzer
     * </p>
     *
     * @param number_of_shards   索引的分片数，默认1
     * @param number_of_replicas 索引副本数，默认0
     * @return co.elastic.clients.elasticsearch.indices.IndexSettings.Builder
     * @author lxw
     * @date 2024/12/7 12:23
     **/
    public static IndexSettings.Builder initSetting(Integer number_of_shards, Integer number_of_replicas) {
        IndexSettings.Builder indexSettingBuilder = new IndexSettings.Builder();
        indexSettingBuilder
                .numberOfShards(String.valueOf(number_of_shards == null ? 1 : number_of_shards))
                .numberOfReplicas(String.valueOf(number_of_replicas == null ? 0 : number_of_replicas))
                .maxNgramDiff(2)
                .maxResultWindow(10000)
                .analysis(an -> an
                        .normalizer("my_normalizer", n -> n
                                .custom(c -> c
                                        .filter(List.of("lowercase", "asciifolding", "trim"))
                                        .charFilter(List.of("my_char_filter"))
                                )
                        )
                        .tokenizer("ngram_tokenizer", t -> t
                                .definition(dd -> dd.ngram(nn -> nn
                                                .minGram(1)
                                                .maxGram(1)
                                                .tokenChars(TokenChar.Letter, TokenChar.Digit)
                                        )
                                )
                        )
                        .analyzer("my_analyzer", a -> a
                                .custom(c -> c
                                        .charFilter(List.of("my_char_filter"))
                                        .tokenizer("ik_max_word")
                                )
                        )
                        .analyzer("ngram_analyzer", a -> a
                                .custom(c -> c
                                        .tokenizer("ngram_tokenizer")
                                        .filter("lowercase")
                                )
                        )
                        .charFilter("my_char_filter", f -> f
                                .definition(d -> d
                                        .patternReplace(p -> p
                                                .pattern("-|\\.")
                                                .replacement(" ")
                                        ))
                        )
                );
        return indexSettingBuilder;
    }


    /**
     * 初始化 TypeMapping 示例，根据业务更改 properties属性的内容
     *
     * @return co.elastic.clients.elasticsearch._types.mapping.TypeMapping.Builder
     * @author lxw
     * @date 2024/7/31 13:52
     **/
    public static TypeMapping.Builder initTypeMapping() {
        TypeMapping.Builder typeMappingBuilder = new TypeMapping.Builder();
        typeMappingBuilder.properties("id", f -> f.integer(i -> i))
                .properties("table_en_name", f -> f.keyword(k -> k))
                .properties("no", f -> f.keyword(k -> k))
                .properties("create_time", f -> f.date(d -> d.format("yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy-MM || yyyy || epoch_millis")))
                .properties("classify_custom", f -> f.keyword(k -> k))
                .properties("subject_codes", f -> f.keyword(k -> k))
                .properties("full_text", f -> f.text(text -> text
                        .analyzer("ngram_analyzer")
                        .fields("ik", fs -> fs
                                .text(t -> t
                                        .analyzer("ik_max_word")
                                        .searchAnalyzer("ik_smart")
                                )
                        )
                ));
        return typeMappingBuilder;
    }

    /**
     * 根据类型，构造ES的 Property
     * <p>
     * 默认ngram分词： ngram_analyzer <br/>
     * ik分词：analyzer:ik_max_word <br/>
     * searchAnalyzer==> ik_smart <br/>
     * </p>
     *
     * @param type       表字段类型
     * @param participle 是否分词;0、否，1、是
     * @return co.elastic.clients.elasticsearch._types.mapping.Property
     * @author lxw
     * @date 2024/7/22 13:57
     **/
    public static Property getPropertyByType(String type, Integer participle) {

        Property.Builder property = new Property.Builder();
        if (type.equalsIgnoreCase("int")) {
            return property.integer(in -> in).build();

        } else if (type.equalsIgnoreCase("long")) {
            return property.long_(l -> l).build();

        } else if (type.equalsIgnoreCase("date")
                || type.equalsIgnoreCase("datetime")) {
            return property.date(d -> d.format("yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || yyyy-MM || yyyy || epoch_millis")).build();
        } else if (type.equalsIgnoreCase("varchar")) {
            if (participle == 0) {
                return property.keyword(k -> k).build();
            } else {
                return property.text(text -> text
                                .analyzer("ngram_analyzer")
                                .fields("ik", fs -> fs
                                        .text(t -> t
                                                .analyzer("ik_max_word")
                                                .searchAnalyzer("ik_smart")
                                        )
                                )
                                .fields("keyword", fs -> fs
                                        .keyword(fk -> fk)
                                ))
                        .build();
            }
        } else if (type.equalsIgnoreCase("text")
                || type.equalsIgnoreCase("longtext")) {
            if (participle == 0) {
                return property.text(t -> t).build();
            } else {
                return property.text(text -> text
                                .analyzer("ngram_analyzer")
                                .fields("ik", fs -> fs
                                        .text(t -> t
                                                .analyzer("ik_max_word")
                                                .searchAnalyzer("ik_smart")
                                        )
                                ))
                        .build();
            }
        } else {
            return property.text(t -> t.index(false)).build();
        }
    }


}
